%ifndef BOOT_REALMODEUTILITY_PRINT
%define BOOT_REALMODEUTILITY_PRINT
; 调用 BIOS 打印功能打印 C-Style 字符串
; 只可在实模式下使用
%include "Boot/RealModeUtility/GetCursorPosition.asm"
%include "Boot/RealModeUtility/SetCursorPosition.asm"
; print(WORD page_number, BYTE* string, WORD color)
; @param page_number
; @param string 字符串首址
; @param color 低字节存放颜色属性，高字节用于对齐，无意义
; @remark 

%define PARAM_STRING_OFFSET 4
%define PARAM_COLOR_OPTION_OFFSET 6
%define PARAM_COLOR_PALETTE_OFFSET 7
bits 16
Boot.RealModeUtility.Print:
Boot.RealModeUtility.Print.Initialize:
    pusha
    mov bp, sp
    push word 0 ; short position = 0;
    ; 函数调用，获取光标地址
    lea di, [bp - 2] ; di = &position;
    push di ; &position
    push word [bp + 18] ; page_number
    call Boot.RealModeUtility.GetCursorPosition ; 获取光标地址
    add sp, 2 * 2

    ; 打印字符串前准备
    mov si, [bp + 20] ; 字符串首址
    mov ah, 0x09 ; 子功能 09H 打印字符串
    mov bh, [bp + 18] ; page_number
    mov cx, 1 ; 每个字符打印 1 次
    mov bl, [bp + 22] ; 字符颜色属性
    dec si ; 首字符前一个位置
Boot.RealModeUtility.Print.PutNextChar:
    inc si
    mov al, [si] ; 取出下个字符
    ; if (al == 0)
    cmp al, 0x00 ; 是否为结束符
    je Boot.RealModeUtility.Print.Return ; 结束
    ; else if (al == '\r')
    cmp al, 0x0d ; 是否为回车符
    je Boot.RealModeUtility.Print.CarriageReturn ; 回车
    ; else if (al == '\n')
    cmp al, 0x0a ; 是否为换行符
    je Boot.RealModeUtility.Print.LineFeed ; 换行
    ; else
    int 0x10 ; 可打印字符
    ; 打印完一个字符后，光标后移一位
    inc word [bp - 2] ; position++;
    push word [bp - 2] ; param position
    push word [bp + 18] ; param page_number
    call Boot.RealModeUtility.SetCursorPosition
    add sp, 2 * 2
    jmp Boot.RealModeUtility.Print.PutNextChar
Boot.RealModeUtility.Print.Return:
    add sp, 2 ; 回收 position 占用的内存
    popa
    ret
Boot.RealModeUtility.Print.CarriageReturn: 
    and word [bp - 2], 0xFF00 ; position 高字节为行，低字节为列，将列数清零
    push word [bp - 2] ; position
    push word [bp + 18] ; page_number
    call Boot.RealModeUtility.SetCursorPosition
    add sp, 2 * 2
    jmp Boot.RealModeUtility.Print.PutNextChar
Boot.RealModeUtility.Print.LineFeed: 
    add word [bp - 2], 0x0100 ; position 高字节为行，低字节为列，行数增 1
    push word [bp - 2] ; position
    push word [bp + 18] ; page_number
    call Boot.RealModeUtility.SetCursorPosition
    add sp, 2 * 2
    jmp Boot.RealModeUtility.Print.PutNextChar
%undef PARAM_STRING_OFFSET
%undef PARAM_COLOR_OPTION_OFFSET
%undef PARAM_COLOR_PALETTE_OFFSET
%endif